

#include "../../system/config.h"
#include "connection.h"
#include "../../constant.h"

#include "../../Proxy.h"
#include "../../Session.h"

#include "../../Proxy.h"
#include "../../NState/Static.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/Reward.h"
#include "../../NLogic/UserLocation.h"

#include "../../Config.h"
#include "../../../../protocol/iFriends.h"
#include "../../NResource/Static.h"


namespace ProjectZ { namespace NCommand { namespace NConnection {

void checkNickname(std::string & nickname)
{
	for (int i = 0; i< nickname.length(); i++)
	{
		if ('\'' == nickname[i])
		{
			nickname[i] = ' ';
		}
	}
}

void CS_REQ_LOGIN::OnExecute(User * pUser, ::Network::Packet * pPacket)
{
	/*
	 * /// 로그인 요청 C -> S
	CS_REQ_LOGIN	0x090B
	{
		u16	u16version;						/// version
		str struser_id;						/// 카카오톡 사용자 아이디(GUID)  login ID 17자리
		str struser_nickname;				/// 카카오톡 사용자 닉네임.
		str struser_profile_image_url;		/// 카카오톡 프로필 이미지 URL
		u8 u8message_blocked;				/// 카카오톡 메시지 블락 여부. ( 0 : No Blocked, 1: Blocked)

		u8 u8IsAuth;							/// 인증을 받았는지 여부
		str struuid;							/// uuid 정보

		u8	company;							/// company
		u8	sale_code;							/// sale_code
	}

	//로그인 요청 S -> C
	SC_REQ_LOGIN	0x090C
	{
		s16 s16ack;						/// 1 : 로그인완료  -1 : 접속오류
		u32	u32gid						/// 내 gid
	}
	 *
	 */

	PROCESSLOG("[CHANNEL] ----------------------------------------");
	PROCESSLOG("[CHANNEL] CS_REQ_LOGIN::OnExecute");
	PREPARE_PACKET;
	//pUser->latency_info.LastPacketTime = NF::GetTickCount();

	uint16_t u16version = 0;
	Toolkit::Str<18> struser_id;
	Toolkit::Str<81> struser_nickname;
	Toolkit::Str<300> struser_profile_image_url;
	uint8_t isblocked = 0;
	uint8_t u8IsAuth = 0;
	Toolkit::Str<50> struuid;
	uint8_t company;
	uint8_t sale_code;

//	* pPacket >> u16version >> struser_id >> struser_nickname >> struser_profile_image_url >> isblocked >> u8IsAuth >> struuid
	* pPacket >> u16version >> struser_id >> struser_nickname >> struser_profile_image_url >> isblocked >> u8IsAuth >> struuid
		>> company >> sale_code;

	if(true == ::ProjectZ::Config::Instance().GetResourceDatabase()._isBlock)
	{
		if( false == NResource::Static::Instance().GetAllowUserResource()->IsAllowUser(struser_id.c_str()) )
			return;
	}
//	if(17 != struser_id.size())
//	{
//		DEBUGLOG("[CHANNEL CS_REQ_LOGIN] social id[%s] : %d", &struser_id[0], atoll(&struser_id[0]));
//		sendAck(pUser, ACK_UNKNOWN_ERROR);
//		return;
//	}

	int index = 0;
	while(struser_id[index] != '\0')
	{
		int value = (int)struser_id[index] - 48;
		if(0 > value || 9 < value)
		{
			DEBUGLOG("[CHANNEL CS_REQ_LOGIN] social id[%s] : %d", struser_id.c_str(), atoll(struser_id.c_str()));
			sendAck(pUser, ACK_UNKNOWN_ERROR);
			return;
		}
		index++;
	}

	STRESSLOG("CS_REQ_LOGIN SOCIALID : %s", struser_id.c_str());

	// 버전 확인
	if (false == NResource::Static::Instance().GetVersionResource()->IsAllowConnection(company, u16version))
	{
		DEBUGLOG("[CHANNEL CS_REQ_LOGIN] ACK_VERSION_MISMATCH client : %d", u16version);
		sendAck(pUser, ACK_VERSION_MISMATCH);
		return;
	}

	DEBUGLOG("struser_id : %s", struser_id.c_str());
	DEBUGLOG("struser_nickname : %s", struser_nickname.c_str());
	DEBUGLOG("struser_profile_image_url : %s", struser_profile_image_url.c_str());

	pUser->SetSocialID(struser_id.c_str());
	std::string strNickName = struser_nickname.c_str();
	checkNickname(strNickName);

	pUser->SetUserNickName(strNickName.c_str());

	DEBUGLOG("usernick : %s", pUser->GetUserNickName().c_str());

	pUser->Setuuid(struuid.c_str());

	pUser->SetEncryptKey(::ProjectZ::Encryption::Instance().GetKey());

	pUser->SetCompany(company);
	pUser->SetSaleCode(sale_code);
	pUser->SetVersion(u16version);

//	pUser->SetCompany(4);
//	pUser->SetSaleCode(38);

	int isBlock = 0;

	// loing fail....
	if (false == loginQuery(pUser, strNickName.c_str(), struser_profile_image_url.c_str(), struuid.c_str(), isBlock))
	{
		DEBUGLOG("[CHANNEL CS_REQ_LOGIN] ACK_DB_ERROR");
		sendAck(pUser, ACK_DB_ERROR);
		return;
	}

	if (true == isBlock)
	{
		DEBUGLOG("[CHANNEL CS_REQ_LOGIN] BLOCK USER GID : %d", pUser->GetUserSeq());
		sendAck(pUser, ACK_BLOCK_USER);
		return;
	}

	// 중복 로그인 fail...
	if (false == ::ProjectZ::NProxy::Initial(pUser, pUser->GetUserSeq()))
	{
		DEBUGLOG("[CHANNEL CS_REQ_LOGIN] ACK_EXIST_USER SEQ : %d", pUser->GetUserSeq());
		sendAck(pUser, ACK_EXIST_USER);

		User * pOldUser = ::ProjectZ::NProxy::GetUser(pUser->GetUserSeq());

		::Network::Packet * pNoti = ::Network::GETPACKETPOOL()->SEND_NEW();
		* pNoti << static_cast<uint8_t>(1);
		pNoti->MakePacket(CMD_SN_SERVER_MESSAGE);
		pOldUser->Send(pNoti);

		if (pUser->GetUserSeq() != pOldUser->GetUserSeq())
		{
			::Logger::GETLOG()->ToAll(::Logger::OBSERVER, "[CHANNEL CS_REQ_LOGIN] CRITICAL SEQ : %d old seq : %d", pUser->GetUserSeq(), pOldUser->GetUserSeq());
			::ProjectZ::NProxy::RemoveUser(pUser->GetUserSeq());
			return;
		}

		User::State * pState = pOldUser->GetState();
		if (NULL == pState)
			return;

		if (pState == NState::Static::Instance().CLEANUP() && pOldUser->GetRefCount() <= 0)
		{
			::ProjectZ::NProxy::Final(pOldUser);
		}
		else
		{
			pState->OnClose(pOldUser, true);
		}

		return;
	}

//	pUser->SetUniqueID(pUser->GetUserSeq());
	//pUser->SetLogin();

	DEBUGLOG("[CHANNEL CS_REQ_LOGIN] ProjectZ::Initial seq : %d", pUser->GetUserSeq());
	//pUser->SetState(NState::Static::Instance().READYMAINFRIENDLIST());

	::ProjectZ::NProxy::RegistUser(pUser);
	STRESSLOG("[CHANNEL] ----------------------------------------");

	pUser->SetState(NState::Static::Instance().WAITLOCATIONREGIST());

	FriendKillTimerSyn msg;
	::ProjectZ::NProxy::SendFriendsServerFirst(pUser, msg);
}

bool
CS_REQ_LOGIN::loginQuery(User * pUser, const char * nickname, const char * profile_url, const char * uuid, int & isBlock)
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_info_login('%s', '%s', '%s', %d, %d, '%s')", pUser->GetSocialID().c_str(), nickname, profile_url
			, pUser->GetUserInfo().company, pUser->GetUserInfo().sale_code, uuid);
	STRESSLOG("CS_REQ_LOGIN::loginQuery : %s", clsAuto->GetQueryString());
	if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	if (0 == clsAuto->ResultRowCount())
		return false;

	int userseq = 0;
	int lastLoginTime = 0;
	int is_Block = 0;
	while( clsAuto->Next() )
	{
		clsAuto->GetRecord() >> userseq >> lastLoginTime >> is_Block;
	}
	pUser->SetUserSeq(userseq);
	isBlock = is_Block;

	pUser->SetAllDailyEPTime(lastLoginTime);
	return true;
}

void
CS_REQ_LOGIN::sendAck(User * pUser, int result)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	pAck->Write2(result);
	* pAck << pUser->GetUserSeq();
	pAck->MakePacket(CMD_SC_REQ_LOGIN);
	pUser->Send(pAck);
}


} /*NWorld*/ } /*NCommand*/ } /*ProjectZ*/

